//
// Created by u on 23-6-29.
//

#ifndef MOSQUITTO_TEST_MQTTMSGPARSE_HPP
#define MOSQUITTO_TEST_MQTTMSGPARSE_HPP

#include <iostream>
#include <vector>

#include <json.hpp>
#include <MqttCommon.hpp>

using namespace std::chrono_literals;
using namespace std::chrono;

class MqttManager;

class MqttMsgParse {
public:
//	MqttMsgParse(MqttManager* mqttManager) {
//		mqttManager_.reset(mqttManager);
//	}
	/* Basic Utils */


	/* 当前类中发布消息*/
	static bool publish(const Msg& msg) {
		if (mqttClient_)
			mqttClient_->publish(msg.topic, msg.payload, msg.qos);
		return true;
	}

	/* 设置Mqtt客户端 */
	static void setMqttClient(const std::shared_ptr<MqttClient>& mqttClient) {
		if (mqttClient_ == mqttClient)
			return;
		mqttClient_ = mqttClient;
	}


//	/* 构建与云端交互最外层结构 */
//	static nlohmann::json buildTop(const std::string& msgId,
//		const std::unordered_map<std::string, nlohmann::json>& data) {
//		// 创建 JSON 对象
//		nlohmann::json top;
//		// 设置 globalMsgId 和 time 字段
//		top["globalMsgId"] = msgId;
//		top["time"] = getLocalTimeStampMs();
//		top["data"] = data;
//		return top;
//	}
//
//	/* 构建与云端交互 devs 层结构 */
//	static nlohmann::json buildDevs(const std::vector<nlohmann::json>& dev) {
//		nlohmann::json data;
//		data["devs"] = dev;
//		return data;
//	}
//
//	/* 构建与云端交互 dev 层结构 */
//	static nlohmann::json buildDev(
//		const std::string& devKey,
//		const std::unordered_map<std::string, nlohmann::json>& points) {
//		nlohmann::json dev;
////		dev["prodKey"] = prodKey;
//		dev["devKey"] = devKey;
//		dev["points"] = points;
//		return dev;
//	}
//
//	/* 构建与云端交互 dev 层结构 */
//	static nlohmann::json buildDev(
//		const std::string& prodKey,
//		const std::string& devKey,
//		const std::unordered_map<std::string, nlohmann::json>& points={}) {
//		nlohmann::json dev;
//		dev["prodKey"] = prodKey;
//		dev["devKey"] = devKey;
//		dev["points"] = points;
//		return dev;
//	}
//
//	/* 构建与云端交互 point 层结构*/
//	template<class T>
//	static nlohmann::json buildPoint(const std::string& act, const T& value, const std::string& res) {
//		nlohmann::json j;
//		j["act"] = act;
//		j["val"] = value;
//		j["res"] = res;
////		j["rpt"] = getLocalTimeStampMs();
//		return j;
//	}


	/* Business */
	/* 接收处理线程 */
	static bool parseMsg(const Msg& msg) {
		std::cout << msg;
//		if (
//			msg.topic.find("dev") != std::string::npos &&
//				msg.topic.find("sub/point/report") != std::string::npos) {
//			return cloudDownSendQueryDataPointMsgParse(msg);
//		}
//		else
		if (
			msg.topic.find("dev") != std::string::npos &&
				msg.topic.find("topo/change") != std::string::npos) {
			// 添加子设备拓扑结构
			return cloudDownSendTopoAdd(msg);
		} else if (
			msg.topic.find("dev") != std::string::npos &&
				msg.topic.find("actions/execute") != std::string::npos) {
			// 控制设备
			return cloudDownSendDeviceControlMsgParse(msg);
		}
		else if (
			msg.topic.find("dev") != std::string::npos &&
				msg.topic.find("dev_canopen_reply") != std::string::npos
			) {
			return deviceReplyMsgParse(msg);
		}
		else if (msg.topic.find("example")) {
			return example();
		}
		else {
			return true;
		}
	}

	/* 云端下发查询消息处理 */
	static bool cloudDownSendQueryDataPointMsgParse(const Msg& msg) {

		const auto& j = nlohmann::json::parse(msg.payload);

		if (j.count("globalMsgId")) {
			std::string msgId = j.at("globalMsgId");
			std::cout << "[globalMsgId] " << msgId << std::endl;
		}

		if (j.count("time")) {
			uint64_t time = j.at("time");
			std::cout << "[time] " << time << std::endl;
		}

		if (j.count("data") && j.at("data").count("devs")) {
			const auto& devs = j.at("data").at("devs");
			for (const auto& dev : devs) {

				std::cout << "============================================" << std::endl;
				if (dev.count("prodKey")) {
					std::cout << "[data][devs][prodKey] " << dev.at("prodKey") << std::endl;
				}

				if (dev.count("devKey")) {
					std::cout << "[data][devs][devKey] " << dev.at("devKey") << std::endl;
				}
				// 处理 point 对象
				if (dev.count("points")) {
					std::cout << "[data][devs][points] " << dev.at("points").size() << std::endl;
					const auto& points = dev.at("points");

					if (points.count("color")) {
						std::cout << "[data][devs][points][color] val: "
								  << points.at("color").at("val")
								  << " rpt: "
								  << points.at("color").at("rpt")
								  << std::endl;
					}

					if (points.count("brightness")) {
						std::cout << "[data][devs][points][brightness] val: "
								  << points.at("brightness").at("val")
								  << " rpt: "
								  << points.at("brightness").at("rpt")
								  << std::endl;
					}

					if (points.count("temperature")) {
						std::cout << "[data][devs][points][temperature] val: "
								  << points.at("temperature").at("val")
								  << " rpt: "
								  << points.at("temperature").at("rpt")
								  << std::endl;
					}

					if (points.count("list")) {
						const auto& list = points.at("list");
						if (list.count("val")) {
							std::vector<int> listVal = list.at("val").get<std::vector<int>>();
							std::cout << "[data][devs][points][list] val size: " << listVal.size() << " val:";
							for (const auto& val : listVal) {
								std::cout << " " << val;
							}
							std::cout << std::endl;
						}

						std::cout << "[data][devs][points][list] rpt: " << points.at("list").at("rpt") << std::endl;
					}
				}
			}
		}
		return true;
	}


	/* 示例程序 */
	static bool example() {
//		const auto& color = buildPoint("red");
//		const auto& brightness = buildPoint(1);
//		const auto& temperature = buildPoint(
//			std::unordered_map<std::string, int>(
//				{
//					{ "maxVal", 142 },
//					{ "minVal", 12 }}));
//		const auto& list = buildPoint(std::vector<int>{ 12, 3, 5 });
//
//		const auto& dev = buildDev(
////			"a1234******",
//			"deviceKey1234",
//			{
//				{ "color", color },
//				{ "brightness", brightness },
//				{ "temperature", temperature },
//				{ "list", list }});
//
//		const auto& dev1 = buildDev(
////			"a1234******",
//			"deviceKey1234",
//			{{ "color", color }});
//
//		const auto& data = buildDevs({ dev, dev1 });
//
//		const auto& top = buildTop("45lk123123****", data);
//
//		const std::string& s = buildMqttStreamMsg(top);
//
//		publish({ "/example_send", s });
//		std::cout << s << std::endl;
		return true;
	}

	/* 初始化函数，包括定时发送，基本上不动，只需要添加任务就可以了 */
	static void MqttParseInit(const std::shared_ptr<MqttClient>& mqttClient) {
		setMqttClient(mqttClient);
		fixedTimeTask();
	}



	static void fixedTimeReport_1s() {
		std::cout << "fixedTimeReport_1s: " << getLocalTimeStampS() << std::endl;
//		publish({ "/fixedTimeReport_1s", std::to_string(getLocalTimeStampS()) });
		example();
	}



	static void fixedTimeReport_10s() {
		std::cout << "fixedTimeReport_10s: " << getLocalTimeStampS() << std::endl;
//		publish({ "/fixedTimeReport_10s", std::to_string(getLocalTimeStampS()) });
	}

	static const std::string& getMsgId() {
		static long counter{0};
		globalMsgId = std::to_string(counter);
		counter++;
		return globalMsgId;
	}

//
//	static nlohmann::json buildPointElectricity(const int& data) {
//		return buildPoint(data);
//	}
//
//	static nlohmann::json buildPointDeviceParm() {
//		const auto& unlock = buildPoint(1);
//		const auto& open = buildPoint(1);
//		const auto& close = buildPoint(0);
//		const auto& productModel = buildPoint("abcdefghijk");
//		const auto& isSupportLight = buildPoint(1);
//		const auto& currentModel = buildPoint(1);
//		const auto& leakStatus = buildPoint(1);
//		const auto& switchStatus = buildPoint(1);
//
//		nlohmann::json json{
//			{ "unlock", unlock },
//			{ "open", open },
//			{ "close", close },
//			{ "productModel", productModel },
//			{ "isSupportLight", isSupportLight },
//			{ "currentModel", currentModel },
//			{ "leakStatus", leakStatus },
//			{ "switchStatus", switchStatus }
//		};
//		return json;
//	}
//
//	static nlohmann::json buildPointPower(const int& data) {
//		return buildPoint(data);
//	}
//
//	static nlohmann::json buildPointPublicDataParm() {
//		const auto& power = buildPoint(1);
//		const auto& sver = buildPoint("V1.0.0");
//		const auto& hver = buildPoint("V1.0.0");
//		const auto& modbus = buildPoint(2);
//		nlohmann::json json{
//			{ "power", power },
//			{ "sver", sver },
//			{ "hver", hver },
//			{ "modbus", modbus }
//		};
//		return json;
//	}
//
//	static nlohmann::json buildPointElecCurrent() {
//		const auto& Ia = buildPoint("12");
//		const auto& Ib = buildPoint("13");
//		const auto& Ic = buildPoint("14");
//		const auto& Id = buildPoint("15");
//		nlohmann::json json{
//			{ "Ia", Ia },
//			{ "Ib", Ib },
//			{ "Ic", Ic },
//			{ "Id", Id }
//		};
//		return json;
//	}
//
//	static nlohmann::json buildPointTempAndFreq() {
//		const auto& Temp = buildPoint("25.5");
//		const auto& Fre = buildPoint("1");
//
//		nlohmann::json json{
//			{ "Temp", Temp },
//			{ "Fre", Fre }
//		};
//		return json;
//	}
//
//	static nlohmann::json buildPointPowerFactor() {
//		const auto& PFa = buildPoint("12");
//		const auto& PFb = buildPoint("13");
//		const auto& PFc = buildPoint("14");
//		const auto& PFt = buildPoint("15");
//		nlohmann::json json{
//			{ "PFa", PFa },
//			{ "PFb", PFb },
//			{ "PFc", PFc },
//			{ "PFt", PFt }
//		};
//		return json;
//	}
//
//	static nlohmann::json buildPointPower() {
//		const auto& Pa = buildPoint("0");
//		const auto& Pb = buildPoint("0");
//		const auto& Pc = buildPoint("0");
//		const auto& Pt = buildPoint("0");
//		const auto& Qa = buildPoint("0");
//		const auto& Qb = buildPoint("0");
//		const auto& Qc = buildPoint("0");
//		const auto& Qt = buildPoint("0");
//		const auto& Sa = buildPoint("0");
//		const auto& Sb = buildPoint("0");
//		const auto& Sc = buildPoint("0");
//		const auto& St = buildPoint("0");
//		nlohmann::json json{
//			{ "Pa", Pa }, { "Pb", Pb }, { "Pc", Pc }, { "Pt", Pt },
//			{ "Qa", Qa }, { "Qb", Qb }, { "Qc", Qc }, { "Qt", Qt },
//			{ "Sa", Sa }, { "Sb", Sb }, { "Sc", Sc }, { "St", St }
//		};
//		return json;
//	}
//
//	static nlohmann::json buildPointVoltage() {
//		const auto& Ua = buildPoint("12");
//		const auto& Ub = buildPoint("13");
//		const auto& Uc = buildPoint("14");
//		nlohmann::json json{
//			{ "Ua", Ua },
//			{ "Ub", Ub },
//			{ "Uc", Uc }
//		};
//		return json;
//	}

private:
	static std::shared_ptr<MqttManager> mqttManager_;
	static std::vector<FixedTimeTaskStruct> fixedTimeTaskList_;
	static std::string globalMsgId;
};

std::shared_ptr<MqttManager> MqttMsgParse::mqttManager_;
std::vector<FixedTimeTaskStruct> MqttMsgParse::fixedTimeTaskList_;
std::string MqttMsgParse::globalMsgId;

#endif //MOSQUITTO_TEST_MQTTMSGPARSE_HPP
